#include "ParseHandler.h"

#include "ICallDispatcher.h"
#include "XMLElement.h"
#include "XMLAttribute.h"

using namespace XMLSAX::Common;

namespace XMLSAX
{
	namespace Core
	{
		ParseHandler::ParseHandler()
		{
		}

		ParseHandler::~ParseHandler()
		{
		}

		long __stdcall ParseHandler::QueryInterface( const struct _GUID &, void ** )
		{
			return 0;
		}

		unsigned long __stdcall ParseHandler::AddRef( void )
		{
			return 0;
		}

		unsigned long __stdcall ParseHandler::Release()
		{
			return 0;
		}

		HRESULT STDMETHODCALLTYPE ParseHandler::putDocumentLocator( ISAXLocator __RPC_FAR *pLocator )
		{
			return S_OK;
		}

		HRESULT STDMETHODCALLTYPE ParseHandler::startDocument( void )
		{
			return S_OK;
		}

		HRESULT STDMETHODCALLTYPE ParseHandler::endDocument( void )
		{
			return S_OK;
		}

		HRESULT STDMETHODCALLTYPE ParseHandler::startPrefixMapping( const wchar_t __RPC_FAR *pPrefix, int prefixSize, const wchar_t __RPC_FAR *pUri, int uriSize )
		{
			return S_OK;
		}

		HRESULT STDMETHODCALLTYPE ParseHandler::endPrefixMapping( const wchar_t __RPC_FAR *pPrefix, int prefixSize )
		{
			return S_OK;
		}

		HRESULT STDMETHODCALLTYPE ParseHandler::startElement( const wchar_t __RPC_FAR *pNamespaceUri, int uriSize, const wchar_t __RPC_FAR *pLocalName, int localNameSize, const wchar_t __RPC_FAR *pRawName, int rawNameSize, ISAXAttributes __RPC_FAR *pAttributes )
		{
			_document.push(_currentElement);

			std::wstring elementName(pLocalName, localNameSize);
			XMLElement *newElement = new XMLElement();

			newElement->SetName(elementName);

			if(NULL != pAttributes)
			{
				int maxAttributesLength = 0;

				if(SUCCEEDED(pAttributes->getLength(&maxAttributesLength)) && (maxAttributesLength > 0))
				{
					int nameLength = 0;
					int valueLength = 0;

					wchar_t *pAttributeNameBuffer;
					wchar_t *pAttributeValueBuffer;

					for(int i = 0; i < maxAttributesLength; ++i)
					{
						if(SUCCEEDED(pAttributes->getLocalName(i, (const wchar_t**)&pAttributeNameBuffer, &nameLength)))
						{
							if(SUCCEEDED(pAttributes->getValue(i, (const wchar_t**)&pAttributeValueBuffer, &valueLength)))
							{
								std::wstring attributeName(pAttributeNameBuffer, nameLength);
								std::wstring attributeValue(pAttributeValueBuffer, valueLength);

								XMLAttribute *attr = new XMLAttribute(attributeName, attributeValue);
								newElement->AddAttribute(attr);
							}
						}
					}
				}
			}

			_currentElement = newElement;

			return S_OK;
		}

		HRESULT STDMETHODCALLTYPE ParseHandler::endElement( const wchar_t __RPC_FAR *pNamespaceUri, int uriSize, const wchar_t __RPC_FAR *pLocalName, int localNameSize, const wchar_t __RPC_FAR *pRawName, int rawNameSize )
		{
			if(_currentElement != NULL)
			{

#ifdef _DEBUG
				_currentElement->printElement();
#endif
				if(_dispatcher != NULL)
				{
					_dispatcher->Dispatch(_currentElement);
				}

				_currentElement = _document.top();
				_document.pop();

				return S_OK;
			}
			else
			{
				return E_FAIL;
			}
		}

		HRESULT STDMETHODCALLTYPE ParseHandler::characters( const wchar_t __RPC_FAR *pChars, int charsSize )
		{
			if(_currentElement != NULL)
			{
				std::wstring value(pChars, charsSize);

				_currentElement->SetValue(value);

				return S_OK;
			}
			else
			{
				return E_FAIL;
			}
		}

		HRESULT STDMETHODCALLTYPE ParseHandler::ignorableWhitespace( const wchar_t __RPC_FAR *pChars, int charsSize )
		{
			return S_OK;
		}

		HRESULT STDMETHODCALLTYPE ParseHandler::processingInstruction( const wchar_t __RPC_FAR *pTarget, int targetSize, const wchar_t __RPC_FAR *pData, int dataSize )
		{
			return S_OK;
		}

		HRESULT STDMETHODCALLTYPE ParseHandler::skippedEntity( const wchar_t __RPC_FAR *pName, int nameSize )
		{
			return S_OK;
		}

		void ParseHandler::SetCallDispatcher(ICallDispatcher *dispatcher )
		{
			_dispatcher = dispatcher;
		}
	}
}